package cn.tedu.eb_film.controller;

import cn.tedu.eb_film.ex.ServiceException;
import cn.tedu.eb_film.pojo.dto.MovieAddNewDTO;
import cn.tedu.eb_film.pojo.dto.MovieExcelDTO;
import cn.tedu.eb_film.pojo.dto.MovieUpdateDTO;
import cn.tedu.eb_film.pojo.entity.Movie;
import cn.tedu.eb_film.pojo.vo.MovieListVO;
import cn.tedu.eb_film.pojo.vo.MovieStandardVO;
import cn.tedu.eb_film.service.MovieService;
import cn.tedu.eb_film.utils.*;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.fastjson.JSON;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import io.swagger.v3.oas.annotations.parameters.RequestBody;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.validator.constraints.Range;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.*;

/**
 * 电影表的控制层
 *
 * @author daiojie
 * @since 2023/03/17 17:32:31
 *
 */

@Api(tags = "电影表管理模板")
@Slf4j
@RestController
@RequestMapping("/movies")
public class MovieController {
    @Autowired
    private MovieService movieService;

    @PostMapping("/addNew")
    @ApiOperation("添加电影院")
    @ApiOperationSupport(order = 100)
    public JsonResult<Void> addNew(@RequestBody MovieAddNewDTO movieAddNewDTO){
        log.debug("开始处理【添加电影】请求，参数：{}",movieAddNewDTO);
        movieService.addNew(movieAddNewDTO);
        return JsonResult.ok();
    }

    @PostMapping("/{id:[0-9]+}/delete")
    @ApiOperation("根据id删除电影院")
    @ApiOperationSupport(order = 200)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "电影ID", required = true, dataType = "long")
    })
    public JsonResult<Void> deleteById(@PathVariable @Range(min = 1, message = "请提交有效的ID值！") Long id){

        log.debug("开始处理【删除电影】请求，参数：{}",id);
        movieService.deleteById(id);
        return JsonResult.ok();
    }


    @PostMapping("/{id:[0-9]+}/update")
    @ApiOperation("根据id修改电影院数据")
    @ApiOperationSupport(order = 210)
    public JsonResult<Void> updateInfoById(@PathVariable @Range(min = 1, message = "请提交有效的ID值！") Long id,
                                           @RequestBody MovieUpdateDTO movieUpdateDTO){

        log.debug("开始处理【修改电影】请求，参数id：{},参数：{}",id,movieUpdateDTO);
        movieService.updateInfoId(id, movieUpdateDTO);
        return JsonResult.ok();
    }

    @GetMapping("/ExportExcel")
    @ApiOperation("开始下载文件")
    @ApiOperationSupport(order = 211)
    public void exportCourse(HttpServletResponse response) throws IOException{
        log.debug("开始下载文件");
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        String filePrefix="Movie"+ System.currentTimeMillis();
        try {
            //主标题和副标题在excel中分别是是第0和第1行
            List<Integer> columnIndexes = Arrays.asList(0,1);
            //自定义标题和内容策略(具体定义在下文)
            CellStyleStrategy cellStyleStrategy =
                    new CellStyleStrategy(columnIndexes,new WriteCellStyle(), new WriteCellStyle());
            // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
            String fileName = URLEncoder.encode(filePrefix, "UTF-8").replaceAll("\\+", "%20");
            //Content-disposition 的 attachment参数将文件作为附件下载
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
            EasyExcel.write(response.getOutputStream(), Movie.class)
                    .registerWriteHandler(cellStyleStrategy)        //设置表头和内容的策略
                    .sheet("movie")
                    .doWrite(movieService.listReleaseDate());

        } catch (Exception e) {
            log.debug("下载文件失败!"+e);
        }
       log.debug("下载数据大小为:{}");
        log.debug("{}",movieService.listReleaseDate().size());
    }


    @PostMapping("/{id:[0-9]+}/enable")
    @ApiOperation("启用类别")
    @ApiOperationSupport(order = 220)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "类别ID", required = true, dataType = "long")
    })
    public JsonResult<Void> setEnable(@PathVariable @Range(min = 1, message = "请提交有效的ID值！") Long id) {
        log.debug("开始处理【启用电影】的请求，参数：{}", id);
        movieService.setEnable(id);
        return JsonResult.ok();
    }


    @PostMapping("/{id:[0-9]+}/disable")
    @ApiOperation("禁用类别")
    @ApiOperationSupport(order = 221)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "类别ID", required = true, dataType = "long")
    })
    public JsonResult<Void> setDisable(@PathVariable @Range(min = 1, message = "请提交有效的ID值！") Long id) {
        log.debug("开始处理【禁用电影】的请求，参数：{}", id);
        movieService.setDisable(id);
        return JsonResult.ok();
    }


    @PostMapping("/{id:[0-9]+}")
    @ApiOperation("根据id查询电影院数据")
    @ApiOperationSupport(order = 210)
    public JsonResult<MovieStandardVO> getStandardById(@PathVariable @Range(min = 1, message = "请提交有效的ID值！")  Long id){
        MovieStandardVO movie = movieService.getStandardById(id);

        return JsonResult.ok(movie);
    }

    @GetMapping("/listReleaseDate")
    @ApiOperation("根据上映时间展示电影")
    @ApiOperationSupport(order = 300)
    public JsonResult<List<MovieListVO>> licsstReleaseDate(){
        log.debug("开始处理【上映时间展示电影】请求，无参数");
        List<MovieListVO> movieReleaseDateList = movieService.listReleaseDate();
        return JsonResult.ok(movieReleaseDateList);
    }

    @GetMapping("/listReleaseDateCount")
    @ApiOperation("统计整正在上映的总数")
    @ApiOperationSupport(order = 333)
    public JsonResult<Long> listReleaseDateCount(){
        log.debug("开始处理【统计整正在上映的总数】请求，无参数");
        Long size = movieService.listReleaseDateCount();
        return JsonResult.ok(size);
    }

    @GetMapping("/listReleaseDatePage")
    @ApiOperation("分页查询正在上映的电影")
    @ApiOperationSupport(order = 334)
    public JsonResult<List<MovieListVO>> listReleaseDatePage(Long start,Long end){
        log.debug("开始处理【分页查询正在上映的电影】请求，无参数");
        if (start == null || end == null) {
            throw new ServiceException(ServiceCode.ERROR_SELECT,"查询失败");
        }
        List<MovieListVO> movieListVOS = movieService.listReleasePage(start, end);
        return JsonResult.ok(movieListVOS);
    }

    @PostMapping("/listComeSoon")
    @ApiOperation("根据即将上映展示电影")
    @ApiOperationSupport(order = 301)
    public JsonResult<List<MovieListVO>> listComeSoon(String type, String country, String releaseDate){
        log.debug("开始处理【按照即将上映时间查询电影】的业务,type:{},country:{},releaseDate:{}",type,country,releaseDate);
        List<MovieListVO> movieComeSoonList = movieService.listComeSoon(type,country,releaseDate);
        return JsonResult.ok(movieComeSoonList);
    }
    @GetMapping("/listComeSoonAll")
    @ApiOperation("根据即将上映时间展示电影（前端）")
    @ApiOperationSupport(order = 302)
    public JsonResult<List<MovieListVO>> listComeSoonAll(){
        log.debug("开始处理【想看人数展示电影】请求，无参数");
        List<MovieListVO> listComeSoonAll = movieService.listComeSoonAll();
        return JsonResult.ok(listComeSoonAll);
    }

    @GetMapping("/listRelease")
    @ApiOperation("根据正在上映时间展示电影（前端）")
    @ApiOperationSupport(order = 303)
    public JsonResult<List<MovieListVO>> listRelease(){
        log.debug("开始处理【想看人数展示电影】请求，无参数");
        List<MovieListVO> listRelease = movieService.listRelease();
        return JsonResult.ok(listRelease);
    }

    @PostMapping("/listSearch")
    @ApiOperation("根据搜索条件展示电影")
    @ApiOperationSupport(order = 311)
    public JsonResult<List<MovieListVO>> listSearch(
            String znName,String type, String country, String releaseDate){
        log.debug("开始处理【按照搜索条件查询电影】的业务,type:{},country:{},releaseDate:{}",type,country,releaseDate);
        List<MovieListVO> movieSearchList = movieService.listSearch(znName,type,country,releaseDate);
        return JsonResult.ok(movieSearchList);
    }
    @PostMapping("/SearchMovie")
    @ApiOperation("根据搜索名字展示电影")
    @ApiOperationSupport(order = 312)
    public JsonResult<List<MovieListVO>> SearchMovie(String znName){
        log.debug("开始处理【按照搜索条件查询电影】的业务,参数为：{}",znName);
        List<MovieListVO> movieSearchList = movieService.searchMovie(znName);
        return JsonResult.ok(movieSearchList);
    }
    @GetMapping("/listTop")
    @ApiOperation("根据名字搜索分页显示")
    @ApiOperationSupport(order = 4)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "page", value = "页码", example = "1"),
            @ApiImplicitParam(name = "pageSize", value = "每页显示的数量", example = "10")
    })
    public JsonResult<JsonPage<MovieListVO>> listTop(String znName, Integer page, Integer pageSize){
        log.debug("开始处理【按照名字搜索分页显示】请求，参数为：{},{},{}", znName, page, pageSize);
        JsonPage<MovieListVO> topList = movieService.listTop(znName, page, pageSize);
        return JsonResult.ok(topList);
    }

    @GetMapping("/listNumberWantToSee")
    @ApiOperation("根据想看人数展示电影")
    @ApiOperationSupport(order = 312)
    public JsonResult<List<MovieListVO>> listNumberWantToSee(){
        log.debug("开始处理【想看人数展示电影】请求，无参数");
        List<MovieListVO> movieNumberWantToSeeList = movieService.listNumberWantToSee();
        return JsonResult.ok(movieNumberWantToSeeList);
    }

    @GetMapping("/listScore")
    @ApiOperation("根据评分高低展示电影")
    @ApiOperationSupport(order = 313)
    public JsonResult<List<MovieListVO>> listScore(){
        log.debug("开始处理【评分高低展示电影】请求，无参数");
        List<MovieListVO> movieScoreList = movieService.listScore();
        return JsonResult.ok(movieScoreList);
    }

    @GetMapping("/listBoxOffice")
    @ApiOperation("根据票房高低展示电影")
    @ApiOperationSupport(order = 314)
    public JsonResult<List<MovieListVO>> listBoxOffice(){
        log.debug("开始处理【票房高低展示电影】请求，无参数");
        List<MovieListVO> movieBoxOfficeList = movieService.listBoxOffice();
        return JsonResult.ok(movieBoxOfficeList);
    }

    @PostMapping("/pageMovie")
    @ApiOperation("分页查询所有电影")
    @ApiImplicitParams({
            @ApiImplicitParam(value = "页码",name="page",example = "1"),
            @ApiImplicitParam(value = "每页条数",name="pageSize",example = "10")
    })
    public JsonResult<JsonPage<MovieListVO>> pageMovie(Integer page, Integer pageSize){
        log.debug("开始处理分页查询所有电影请求，page:{},pageSize:{}",page,pageSize);
        JsonPage<MovieListVO> jsonPage=
                movieService.getAllMovieByPage(page,pageSize);


        return JsonResult.ok(jsonPage);


    }

    @PostMapping("/addExcelNew")
    @ApiOperation("批量添加电影")
    @ApiOperationSupport(order = 400)
    public JsonResult<Void> addExcelNew(MultipartFile file)   {
        log.debug("开始处理【批量添加电影】请求，无参数");
//        1、使用实现ReadListener的方式
//        EasyExcel.read(file.getInputStream(),CourseInfo.class, new UploadDataListener(courseInfoMapper)).sheet().doRead();
//        2、使用继承AnalysisEventListener的方式
//        EasyExcel.read(file.getInputStream(), CourseInfo.class,new CourseInfoListener(courseService)).sheet().doRead();
//        3、使用继承AnalysisEventListener且使用泛型的方式：
//        3.1、建立一个通用的读取监听器，在该监听器读取到数据，并使用List保存，读取完成之后，使用getList()方法获得
        GeneralListener<MovieExcelDTO> generalListener = new GeneralListener<>();
//        3.2、执行Excel的读取，.read()方法需要传入三个参数：1、文件。2、实体类。3、监听器。
        try {
            EasyExcel.read(file.getInputStream(),MovieExcelDTO.class,generalListener).sheet().doRead();
        } catch (IOException e) {
            throw new ServiceException(ServiceCode.ERROR_CONFLICT,"批量添加电影文件失败");
        }
        log.info("读取到的数据大小为:{}", JSON.toJSONString(generalListener.getList().size()));
        //        3.3、获得监听器读取的数据列表
        List<MovieExcelDTO> movieExcelDTOList = generalListener.getList();
        for (MovieExcelDTO movieExcelDTO : movieExcelDTOList) {
            log.debug(".............movieExcelDTO:{}",movieExcelDTO);
        }
//        3.4、执行后续入库操作
        movieService.addExcelList(movieExcelDTOList);

        return JsonResult.ok();
    }




}














